﻿using System;
using System.Linq;
using KxParser.Lexer.Common;

namespace KxParser.Parser.LR0
{
    public class Lr0Parser
    {
        private ParsingProcedure parsingProcedure;

        public Lr0Parser(string[] productions, string [] terminals, string[] nonTerminals)
        {
            var p = productions.Select(production => new ProductionItem(production)).ToList();
            Global.ProductionItems = p.ToArray();
            Global.Terminals = terminals;
            Global.NonTerminals = nonTerminals;

            if(HasDuplicates())
            {
                Console.WriteLine("Duplicate items in terminals and non-terminals are not allowed!");
                return;
            }
        }

        private bool HasDuplicates()
        {
            return (from terminal in Global.Terminals
                    from nonTerminal in Global.NonTerminals
                    where terminal.Equals(nonTerminal)
                    select terminal).Any();
        }

        public bool Parse(Token[] inputTokens)
        {
            try
            {
                Global.InputTokens = inputTokens;

                var dfa = new DFA(); 

                var parserTable = new ParserTable(dfa.GetStates());

                Console.WriteLine(parserTable);

                parsingProcedure = new ParsingProcedure(parserTable, dfa.GetStates(), Global.InputTokens);
                return parsingProcedure.Parse();
            }catch(Exception exception)
            {
                throw new Exception(exception.Message);
            }
        }

        public Token GetErrorToken()
        {
            return parsingProcedure.GetErrorToken();
        }
    }
}
